package com.ruoyi.framework.config;

import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import jakarta.ws.rs.client.ClientBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.ClientBuilderWrapper;
import org.keycloak.admin.client.JacksonProvider;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.RealmResource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Data
@Configuration
@ConfigurationProperties(prefix = "keycloak-admin-api")
@Slf4j
public class KeycloakAdminApiConfig {

    private String serverUrl;
    private String realm;
    private String clientId;
    private String clientSecret;
    private String username;
    private String password;

    private Keycloak keycloakInstance;
    private final Lock lock = new ReentrantLock();

    @Resource
    SSLContext sslContext;

    private void buildKeycloak() {
        lock.lock();
        try {
            try{
                cleanup();
                keycloakInstance = null;
            } catch (Exception e) {
                log.warn("Keycloak会话清理异常", e);
            } finally {
                if (keycloakInstance == null || keycloakInstance.isClosed()) {
                    this.keycloakInstance = KeycloakBuilder.builder()
                            .serverUrl(serverUrl)
                            .realm(realm)
                            .clientId(clientId)
                            .clientSecret(StringUtils.defaultIfBlank(clientSecret, null))
                            .username(username)
                            .password(password)
                            .grantType(OAuth2Constants.PASSWORD)
                            .resteasyClient(newRestEasyClient())
                            .build();
                    log.info("成功初始化Keycloak实例");
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("构建Keycloak实例时发生错误", e);
        } finally {
            lock.unlock();
        }
    }

    public synchronized Keycloak getKeycloakInstance() {
        if (keycloakInstance != null && !keycloakInstance.isClosed()) {
            try {
                keycloakInstance.serverInfo(); // 尝试获取服务器信息以验证会话是否有效
            } catch (Exception e) {
                log.warn("Keycloak会话已失效，尝试重新初始化", e);
                buildKeycloak();
            }
        } else {
            buildKeycloak();
        }
        return keycloakInstance;
    }

    public RealmResource realmResource(){
        Keycloak keycloak = getKeycloakInstance();
        if(keycloak != null){
            return keycloak.realm(realm);
        }
        return null;
    }

    @PreDestroy
    public void cleanup() {
        if (this.keycloakInstance != null && !this.keycloakInstance.isClosed()) {
            this.keycloakInstance.close();
        }
    }

    private ResteasyClient newRestEasyClient() {
        ClientBuilder clientBuilder = ClientBuilderWrapper.create(sslContext, false);
        clientBuilder.register(JacksonProvider.class, 100);
        return (ResteasyClient) clientBuilder.build();
    }

}
